home *** CD-ROM | disk | FTP | other *** search
/ NeXT Enterprise Objects Framework 1.1 / NeXT Enterprise Objects Framework 1.1.iso / NextDeveloper / Examples / EnterpriseObjects / SQLExecutor / Evaluator.m < prev    next >
Encoding:
Text File  |  1995-02-09  |  8.3 KB  |  322 lines

  1. /* Evaluator.m:
  2.  * You may freely copy, distribute, and reuse the code in this example.
  3.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  4.  * fitness for any particular use.
  5.  *
  6.  *  
  7.  *
  8.  */
  9.  
  10. #import <foundation/NSString.h>
  11. #import <foundation/NSUtilities.h>
  12.  
  13. #import    "ScrollViewExtras.h"
  14. #import "Evaluator.h"
  15. #import "EOFDelegateAdaptorCategory.h"
  16.  
  17.  
  18. #define FAILURE NXLocalizedString("Failure:", NULL, \
  19.     "Message given to user when an operation has failed.")
  20.  
  21. #define CANNOT_CONNECT NXLocalizedString("Cannot connect to database", NULL, \
  22.     "Message given to user to explain what fails. ")
  23.  
  24. #define OK NXLocalizedString("OK", NULL, "Okay to continue ")
  25.  
  26. @implementation Evaluator
  27.  
  28. - initWithModelFile:(NSString *)filePath
  29. {
  30.     char path[MAXPATHLEN];
  31.     BOOL        result=NO;
  32.     
  33.     [super init];
  34.           
  35.     // open the model file and connect to the database  
  36.     model = [[[EOModel alloc]     
  37.                 initWithContentsOfFile: filePath] autorelease];
  38.                  
  39.     if (!model)
  40.         return nil;
  41.   
  42.     
  43.     adaptor = [EOAdaptor adaptorWithModel:model];
  44.     if (!adaptor) 
  45.         return nil;
  46.    
  47.     context = [adaptor createAdaptorContext];
  48.     if (!context)      
  49.         return nil;
  50.     
  51.         
  52.     channel = [context createAdaptorChannel];
  53.     
  54.     if (!channel)       
  55.         return nil;
  56.    
  57.     if (![channel isOpen])
  58.          result = [channel openChannel];
  59.     if (result)
  60.         [resultsView sprintf:"Connection successful\n"];
  61.     else
  62.         [resultsView sprintf:"Connection failed\n"];
  63.     
  64.     [[NXBundle mainBundle] getPath:path forResource:"SQLWindow" ofType:"nib"];
  65.     [NXApp loadNibFile:path owner:self withNames:NO];
  66.     [(Window *)[resultsView window] setDelegate:self];
  67.     [[resultsView window] setTitleAsFilename:[filePath cString]];
  68.     [[queryView docView] selectAll:self];
  69.     [[resultsView window] makeKeyAndOrderFront:self];
  70.     
  71.     /*----------------------------------------------------------------------
  72.      *    set up the channel delegate to SybaseDelegate for Sybase model files
  73.      *     use EOFDelegateCategory for Oracle model files
  74.      *--------------------------------------------------------------------*/
  75.  
  76.     if ([[adaptor name] isEqualToString:@"Sybase"]) {
  77.         sybaseDelegate = [[SybaseDelegate alloc] init];
  78.         [channel setDelegate:sybaseDelegate];
  79.     }
  80.     else {
  81.         sybaseDelegate = nil;
  82.         [channel setDelegate:[[EOFDelegateAdaptorCategory alloc] init]];
  83.     }
  84.      
  85.      return self;
  86. }
  87.  
  88. - free
  89. {
  90.     [model release];
  91.     [adaptor release];
  92.     [context release];
  93.     [channel release];
  94.     if (sybaseDelegate)
  95.         [sybaseDelegate release];
  96.     
  97.     return [super free];
  98. }
  99.  
  100. - evaluate:sender
  101. {
  102.     BOOL    result = NO;
  103.     int    charCount;
  104.     char *buffer = NULL;
  105.     NSDictionary *row;
  106.  
  107.     /*----------------------------------------------------------------------
  108.      *    get the SQL statement
  109.      *--------------------------------------------------------------------*/
  110.  
  111.     if ((charCount = [[queryView docView] textLength]) > 0) {
  112.     buffer = malloc((charCount+1) * sizeof(char));
  113.     [[queryView docView] getSubstring:buffer start:0 length:charCount];
  114.     buffer[charCount] = 0;
  115.     while (charCount > 0 && buffer[--charCount] == '\n')
  116.         buffer[charCount] = 0;
  117.     [resultsView sprintf:"%s\n", buffer];
  118.     
  119.     }
  120.     else {
  121.     [resultsView sprintf:"Can't execute an empty string!\n"];
  122.     return self;
  123.     }
  124.     
  125.     /*----------------------------------------------------------------------
  126.      *    evaluate the SQL statement
  127.      *--------------------------------------------------------------------*/
  128.  
  129.     [context beginTransaction]; 
  130.     result = [channel evaluateExpression:
  131.             [[NSString alloc] initWithCString:(const char *)buffer]];
  132.     
  133.     if (result){
  134.         [resultsView sprintf:"SQL successfully evaluated\n"];
  135.         
  136.         while ([channel isFetchInProgress] == YES) {
  137.                 // get the array of attributes from the result set 
  138.             attributes = [channel describeResults];
  139.         
  140.                 // since the EO Framework attributes are stored as Attribute1,
  141.                 // Attribute2, etc., build a dictionary to do conversion.
  142.                 
  143.                  [self buildColumnNamesDictionary:attributes];
  144.         
  145.                 // The NSDictionary contains all the data for one row
  146.         while ((row  = [channel fetchAttributes: attributes withZone:
  147.                                     [adaptor zone]]) != nil)                                     
  148.                 // read data back 
  149.             [self readDataFromDict:row ];
  150.      
  151.         }
  152.         [context commitTransaction];
  153.  
  154.     }
  155.     else {
  156.             // do clean-up if SQL statement cannot be evaluated. 
  157.         [resultsView sprintf:"SQL evaluation failed\n"];
  158.         if ([channel isFetchInProgress] == YES)
  159.             [channel cancelFetch];
  160.         [context rollbackTransaction];
  161.     }    
  162.     free(buffer);
  163.     return self;
  164. }
  165.  
  166.  
  167.  
  168. /* Build a dictionary where the Keys are Attribute1, Attribute2, etc.,
  169.  * while the values are the actual column names as specified in the
  170.  * database.
  171.  */
  172. - buildColumnNamesDictionary:(NSArray *) attributesArray
  173. {
  174.     NSEnumerator    *enumerator;
  175.     EOAttribute      *attribute;
  176.     NSMutableArray    *keys = [NSMutableArray array];
  177.     NSMutableArray    *values = [NSMutableArray array];
  178.     
  179.     enumerator = [attributesArray objectEnumerator];
  180.     
  181.     while ((attribute = [enumerator nextObject]) != nil) {
  182.         [keys addObject:[attribute name]];
  183.         [values addObject:[attribute columnName]];
  184.     }
  185.     columnNamesDict = [NSDictionary dictionaryWithObjects:values
  186.                     forKeys: keys];
  187.     return self;
  188. }
  189.  
  190. /* Cycle through the key and value pairs of the dictionary 
  191.  * and print them to result view
  192.  *  
  193.  */
  194. - readDataFromDict:(NSDictionary *) dictionary
  195. {
  196.     NSEnumerator        *keyEnumerator;
  197.     NSString *            key;
  198.     NSString *            newKey;
  199.     id                    value;
  200.     char                buffer[1024];
  201.     SybaseRowType        rowType=0;
  202.     
  203.     keyEnumerator = [dictionary keyEnumerator];
  204.     if (sybaseDelegate)
  205.         rowType = [sybaseDelegate currentRowType];
  206.     
  207.     //print the full dictionary for Sybase regular rows or if the Oracle adaptor is used
  208.     if ( ((sybaseDelegate) &&  (rowType == SybaseRegularRow ))
  209.                 || (sybaseDelegate == nil) )
  210.     {
  211.     while ((key = [keyEnumerator nextObject]) != nil) {
  212.         newKey = [columnNamesDict objectForKey:[key description]];
  213.          
  214.         value = [dictionary objectForKey:key];
  215.         sprintf(buffer, "%s: \t %s\n", [[newKey description] cString],
  216.                     [[(NSObject *)value description] cString]);
  217.         [resultsView sprintf:buffer];
  218.         }
  219.     }
  220.     else {
  221.         // This must be one special sybase row
  222.         switch (rowType) {
  223.         case SybaseComputeRow:
  224.         case SybaseReturnStatusRow:
  225.             // print one row of data only
  226.             key = [keyEnumerator nextObject];
  227.             value = [dictionary objectForKey:key];
  228.             sprintf(buffer, "Row type: %s \t %s\n", (rowType == SybaseComputeRow) ? 
  229.                     "SybaseComputeRow": "SybaseReturnStatusRow",
  230.                     [[(NSObject *)value description] cString]);
  231.             [resultsView sprintf:buffer];
  232.             sprintf(buffer, "************************************\n");
  233.             [resultsView sprintf:buffer];
  234.             break;
  235.         case SybaseReturnParameterRow:
  236.             // Exercise for the reader: How to format this row 
  237.             [resultsView sprintf:"SybaseReturnParameterRow: No data printed\n"];
  238.             break;
  239.         case SybaseRegularRow:
  240.         default:
  241.             break;
  242.         }
  243.     } 
  244.     
  245.         
  246.     return self;
  247. }
  248.  
  249. - clear:sender
  250. {
  251.     [resultsView clear:sender];
  252.     [[queryView docView] selectText:self];
  253.     return self;
  254. }
  255.  
  256. - close:sender
  257. {
  258.     // close the adaptor channel and disconnect from the database  
  259.     [channel closeChannel];
  260.     // close the main window  
  261.     [[NXApp mainWindow] performClose:sender];
  262.     return self;
  263. }
  264.  
  265.  
  266.  
  267. /*--------------------------------------------------------------------------
  268.  *    Announcing Trace Info
  269.  *------------------------------------------------------------------------*/
  270. - (void) logString:(NSString *) aString
  271. {
  272.     [resultsView sprintf: "%s", [aString cString]];
  273. }
  274.  
  275. - (void) announce:sender selector:(SEL)selector
  276. {
  277.     return [self announce:sender selector:selector with:nil];
  278. }
  279.  
  280.  
  281. - (void) announce:sender selector:(SEL)selector with:array
  282. {
  283.     NSMutableString    *string;
  284.     
  285.     string = [NSMutableString stringWithFormat:@"BEGIN> {Sender = %s%s",
  286.         [[(NSObject *)[sender class] description] cString], "}" ];
  287.     
  288.             
  289.     [string appendFormat:@" \n\t{Delegate Method = %s} ", sel_getName(selector)];
  290.  
  291.     if (array)
  292.         {
  293.         id object;
  294.         id verboseString = [NSMutableString stringWithCapacity:0];
  295.         id enumerator = [array objectEnumerator];
  296.         
  297.         while ((object = [enumerator nextObject]) != nil)
  298.             [verboseString 
  299.                 appendFormat:@"\n\t{Argument = %s} \n\t{Argument Description = %s} ", 
  300.                 [[(NSObject *)[object class] description] cString], 
  301.                 [[(NSObject *) object description] cString]];
  302.  
  303.         [string appendString:verboseString];
  304.         }
  305.  
  306.         
  307.     [string appendFormat:@"\n"];
  308.     [resultsView sprintf: "%s", [string cString]];
  309. }
  310.  
  311.  
  312. /* Window Delegate method -- constrain window resizing */
  313.  
  314. - windowWillResize:sender toSize:(NXSize *)frameSize
  315. {
  316.     if ( frameSize->height < 230 ) frameSize->height= 230;
  317.     return self;
  318. }
  319.  
  320.  
  321. @end
  322.